package afk.biglog.gui;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.util.List;

import javax.swing.*;

import afk.biglog.*;

public class FileViewAdapter implements BlockListener, Runnable, ActionListener
{

	private static final String B_FILTER = "B_FILTER";
	private final File file;
	private final BlockFilter filter;

	public File getFile()
	{
		return file;
	}

	public BlockFilter getFilter()
	{
		return filter;
	}

	public JButton getFilterButton()
	{
		return filterButton;
	}

	public JTextArea getFilterText()
	{
		return filterText;
	}

	public JPanel getMainPanel()
	{
		return mainPanel;
	}

	private final JButton filterButton;
	private final JTextArea filterText;
	private final JPanel mainPanel;
	private Thread thread;
	private final JTextArea editor;
	private final JScrollPane jScrollPane;
	private final List<Block> blocks = new ArrayList<Block>();
	private final FileBlockIndexer blockIndexer;

	private final BlockReader blockReader;
	private final ErrorHandler errorHandler;

	public FileViewAdapter(final File file, final String encoding, final int offset, final int linesPerBlock, final ErrorHandler handler, final BlockFilter blockFilter, final JRootPane rootPane) throws FileNotFoundException
	{
		errorHandler = handler;
		this.file = file;
		filter = blockFilter;
		editor = new JTextArea();
		jScrollPane = new JScrollPane(editor);
		editor.setEditable(false);
		editor.setToolTipText(file.getAbsolutePath());
		editor.setFont(new Font("courier new", Font.PLAIN, 12));
		blockIndexer = new FileBlockIndexer(file, linesPerBlock, offset, errorHandler);
		blockIndexer.setFinish(true);
		blockIndexer.addBlockListener(this);

		final Box box = new Box(BoxLayout.X_AXIS);
		filterText = new JTextArea(filter.toString());
		box.add(filterText);
		filterButton = createFilterButton();
		box.add(filterButton);
		mainPanel = new JPanel(new BorderLayout());
		mainPanel.add(box, BorderLayout.NORTH);
		mainPanel.add(jScrollPane, BorderLayout.CENTER);
		blockReader = new BlockReader(file, encoding);

		rootPane.setDefaultButton(filterButton);

	}

	private JButton createFilterButton()
	{
		final JButton filterButton = new JButton("Filter");

		filterButton.setDefaultCapable(true);
		filterButton.addActionListener(this);
		filterButton.setActionCommand(B_FILTER);
		return filterButton;
	}

	public void startIndex()
	{
		thread = new Thread(this, file.getName() + " Indexer");
		thread.start();
	}

	@Override
	public void newBlock(final Block block)
	{
		blocks.add(block);

		try
		{
			// TODO: editor reads on demand
			final String value = blockReader.read(block, filter);
			editor.setText(editor.getText() + value);
		}
		catch (final Throwable e)
		{
			errorHandler.addError("While adding Block " + block + ": ", e);
		}

	}

	@Override
	public void run()
	{
		try
		{
			blockIndexer.index();
		}
		catch (final Exception e)
		{
			errorHandler.addError("While indexing " + file + ": ", e);
		}
	}

	@Override
	public void actionPerformed(final ActionEvent e)
	{
		if (e != null)
			if (e.getActionCommand() == B_FILTER)
			{
				cleanTextArea();
				updateFilter();
				filter();
			}
	}

	private void filter()
	{
		for (final Block block : blocks)
			try
			{
				// TODO: editor reads on demand
				if (editor.getText().length() > 10000)
					return;
				final String value = blockReader.read(block, filter);
				editor.setText(editor.getText() + value);
			}
			catch (final IOException e)
			{
				errorHandler.addError("While filtering Block " + block + ": ", e);

			}

	}

	private void updateFilter()
	{
		filter.getWhiteList().clear();
		filter.getBlackList().clear();
		if (filterText.getText().length() > 0)
		{
			final String[] filters = filterText.getText().split("\r\n");
			for (final String string : filters)
			{
				if (string.startsWith("-"))
					filter.getBlackList().add(string.substring(1));
				if (string.startsWith("+"))
					filter.getWhiteList().add(string.substring(1));
				else
					filter.getWhiteList().add(string);
			}
		}
	}

	private void cleanTextArea()
	{
		editor.setText("");
	}

	public void close()
	{
		try
		{
			blockReader.close();
		}
		catch (final IOException e)
		{
			errorHandler.addError("While closing File " + file + ": ", e);
		}
		blockIndexer.abort();
		thread.interrupt();
	}
}
